package typeops

import (
	"fmt"
)

// DemoTypeConversion 演示基本类型转换
func DemoTypeConversion() {
	fmt.Println("=== 类型转换演示 ===")

	// 数值类型之间的转换
	var i int = 42
	var f float64 = float64(i) // 整数转浮点数
	var u uint = uint(i)       // 整数转无符号整数

	fmt.Printf("整数: %d (类型: %T)\n", i, i)
	fmt.Printf("转浮点数: %f (类型: %T)\n", f, f)
	fmt.Printf("转无符号整数: %d (类型: %T)\n", u, u)

	// 浮点数转整数（会截断小数部分）
	var pi float64 = 3.14159
	var piInt int = int(pi)
	fmt.Printf("浮点数: %f (类型: %T)\n", pi, pi)
	fmt.Printf("转整数: %d (类型: %T)\n", piInt, piInt)

	// 字符串与数值类型的转换
	// 注意：Go没有内置的字符串到数值的隐式转换，需要使用strconv包
	// 这里简单展示字符串的字节表示
	str := "Hello"
	var b byte = str[0] // 获取字符串的第一个字节
	fmt.Printf("字符串: %s\n", str)
	fmt.Printf("第一个字符的字节值: %d (类型: %T)\n", b, b)

	// 复数类型转换
	var c complex128 = complex(3.0, 4.0)
	var realPart float64 = real(c)
	var imagPart float64 = imag(c)
	fmt.Printf("复数: %v (类型: %T)\n", c, c)
	fmt.Printf("实部: %f, 虚部: %f\n", realPart, imagPart)
}

// DemoTypeAssertion 演示接口类型断言
func DemoTypeAssertion() {
	fmt.Println("\n--- 接口类型断言 ---")

	// 定义一个接口变量
	var i interface{}

	// 赋值为整数
	i = 42

	// 类型断言 - 检查是否为int类型
	if v, ok := i.(int); ok {
		fmt.Printf("断言成功: %d 是int类型\n", v)
	} else {
		fmt.Println("断言失败: 不是int类型")
	}

	// 赋值为字符串
	i = "Hello, Go!"

	// 类型断言 - 尝试断言为int类型（会失败）
	if v, ok := i.(int); ok {
		fmt.Printf("断言成功: %d 是int类型\n", v)
	} else {
		fmt.Println("断言失败: 不是int类型")
	}

	// 类型断言 - 正确断言为string类型
	if v, ok := i.(string); ok {
		fmt.Printf("断言成功: %s 是string类型\n", v)
	} else {
		fmt.Println("断言失败: 不是string类型")
	}

	// 使用switch进行类型判断
	demoTypeSwitch(42)
	demoTypeSwitch(3.14)
	demoTypeSwitch("Hello")
	demoTypeSwitch(true)
}

// demoTypeSwitch 使用switch语句进行类型判断
func demoTypeSwitch(i interface{}) {
	fmt.Printf("类型判断 - 值: %v, ", i)
	switch v := i.(type) {
	case int:
		fmt.Printf("类型: int, 平方: %d\n", v*v)
	case float64:
		fmt.Printf("类型: float64, 平方: %f\n", v*v)
	case string:
		fmt.Printf("类型: string, 长度: %d\n", len(v))
	case bool:
		fmt.Printf("类型: bool\n")
	default:
		fmt.Printf("未知类型\n")
	}
}

// DemoTypeInference 演示类型推断
func DemoTypeInference() {
	fmt.Println("\n--- 类型推断 ---")

	// 简短变量声明中的类型推断
	name := "张三"          // 推断为string类型
	age := 30              // 推断为int类型
	score := 95.5          // 推断为float64类型
	isStudent := false     // 推断为bool类型

	fmt.Printf("name: %s (类型: %T)\n", name, name)
	fmt.Printf("age: %d (类型: %T)\n", age, age)
	fmt.Printf("score: %.1f (类型: %T)\n", score, score)
	fmt.Printf("isStudent: %t (类型: %T)\n", isStudent, isStudent)

	// 函数返回值的类型推断
	sum := addNumbers(10, 20)
	fmt.Printf("sum: %d (类型: %T)\n", sum, sum)
}

// addNumbers 返回两个整数的和
func addNumbers(a, b int) int {
	return a + b
}

// DemoTypeMethods 演示为类型添加方法
func DemoTypeMethods() {
	fmt.Println("\n--- 为类型添加方法 ---")

	// 创建一个MyInt类型的变量
	var x MyInt = 10
	var y MyInt = 5

	// 调用方法
	sum := x.Add(y)
	fmt.Printf("%d + %d = %d\n", x, y, sum)

	// 方法可以修改接收者（如果是指针接收者）
	fmt.Printf("调用Double前: %d\n", x)
	x.Double()
	fmt.Printf("调用Double后: %d\n", x)

	// 结构体方法
	person := Person{Name: "李四", Age: 25}
	person.Greet()

	// 指针接收者方法可以修改结构体的字段
	fmt.Printf("修改前年龄: %d\n", person.Age)
	person.Birthday()
	fmt.Printf("修改后年龄: %d\n", person.Age)
}

// MyInt 自定义整数类型
type MyInt int

// Add 为MyInt类型添加Add方法
func (a MyInt) Add(b MyInt) MyInt {
	return a + b
}

// Double 为MyInt类型添加Double方法（指针接收者）
func (a *MyInt) Double() {
	*a = *a * 2
}

// Person 人员结构体
type Person struct {
	Name string
	Age  int
}

// Greet 为Person类型添加Greet方法
func (p Person) Greet() {
	fmt.Printf("你好，我叫%s，今年%d岁\n", p.Name, p.Age)
}

// Birthday 为Person类型添加Birthday方法（指针接收者）
func (p *Person) Birthday() {
	p.Age++
}

// DemoAdvancedTypeOps 展示高级类型操作
func DemoAdvancedTypeOps() {
	// 调用各个演示函数
	DemoTypeConversion()
	DemoTypeAssertion()
	DemoTypeInference()
	DemoTypeMethods()
}